//`timescale 1ns / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company: University of Utah
// Engineer: David Hurst, Tyson Hunt, Chase Hochstrasser
//
// Create Date:   12:02:59 09/06/2011
// Design Name:   ALUUnit
// Module Name:   C:/Users/david/CPU/ALU_test.v
// Project Name:  CPU
// Target Device:  
// Tool versions:  
// Description:  Testing ALU design of each operation / Calculation.
//
// Verilog Test Fixture created by ISE for module: ALUUnit
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments: Displays have been placed in code to show faliures to the user.
// 
////////////////////////////////////////////////////////////////////////////////

module ALU_test;
   
	// Include opcode file
	`include "opcode.v"
	
	// Inputs / registers
	reg [15:0] A;
	reg [15:0] B;
	reg [7:0] op;
	reg Cin;

	// Outputs
	wire [15:0] result;
	wire [4:0] F;
 
	// Integer
   integer i = 0;

	// Instantiate the Unit Under Test (UUT)
	ALUUnit uut (
		.A(A), 
		.B(B), 
		.op(op), 
		.result(result), 
		.F(F),
		.Cin(Cin)
	);

	initial begin
	
		// Initialize Inputs
		A = 0;
		B = 0;
		op = ADD; // use opcode ADD
		
		// Wait 100 ns for global reset to finish
		#100;
		
		$display("Begin Testing"); // Display to user that Testing will begin here.
		
       //$monitor("A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		 for (i = 0; i < 50; i=i+1) begin
		 
		 #10; // Wait 10 ns
		 
		 // randomize values of A and B
	    A = $random % 2^16;
		 B = $random % 2^16;
		 
		 #1 // Really? you want to wait 1 ns now?
		 
		 // check if Adding fails here
		 if(result != ($signed(A)+$signed(B)))
			$display("Failed ADD A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op); // Display to user
		 end
		 
		 // SHIFTS SHIFTS SHIFTS
		 // LSH
		 //
		 op = LSH;
		 #10; // Wait 10 ns
		 A=2'b10;
		 B=1;
		 #1
		 if(result != (1))
				$display("Failed LSH A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		
		 A=4'b1111;
		 B= 3;
		 #1
		 if(result != (1'b1))
				$display("Failed LSH A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		 
		 A=4'b1111;
		 B=0;
		 #1
		 if(result != 15)
				$display("Failed LSH A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		 A=16'hFFFF;
		 B=1;
		 #1
		 if(result != 16'h7FFF)
				$display("Failed LSH A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		 
		 //
		 // LSHI
		 //
		 
		 op = LSHI;
		 A=2'b10;
		 B=16'b1111111111111111;
		 #1
		 if(result != (3'b100))
				$display("Failed LSHI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		 A=2'b10;
		 B=1;
		 #1
		 if(result != (1'b1))
				$display("Failed LSHI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		
		A=4'b1111;
		 B= 3;
		 #1
		 if(result != (1'b1))
				$display("Failed LSHI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		 
		 A=4'b1111;
		 B=0;
		 #1
		 if(result != 15)
				$display("Failed LSHI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);

		 A=16'hFFFF;
		 B=1;
		 #1
		 if(result != 16'h7FFF)
				$display("Failed LSHI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		 //
		 // ASHU
		 //
      op = ASHU;
		 A=2'b10;
		 B=16'b1111111111111111;
		 #1
		 if(result != (3'b100))
				$display("Failed ASHU A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		 A=2'b10;
		 B=1;
		 #1
		 if(result != 1)
				$display("Failed ASHU A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		
		A=16'b1111;
		 B= 3;
		 #1
		 if(result != (1'b1))
				$display("Failed ASHU A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		 
		 A=16'b1111;
		 B=0;
		 #1
		 if(result != 15)
				$display("Failed ASHU A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		 A=16'hFFFF;
		 B=1;
		 #1
		 if(result != 16'hFFFF)
				$display("Failed ASHU A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		 
		 
		 //
		 // ASHUI
		 //
      op = ASHUI;
		 A=2'b10;
		 B=4'b1111;
		 #1
		 if(result != (3'b100))
				$display("Failed ASHUI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		 A=2'b10;
		 B=1;
		 #1
		 if(result != (1'b1))
				$display("Failed ASHUI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		
		A=16'b1111;
		 B= 3;
		 #1
		 if(result != (1'b1))
				$display("Failed ASHUI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		 
		 A=16'b1111;
		 B=0;
		 #1
		 if(result != 15)
				$display("Failed ASHUI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		 A=16'hFFFF;
		 B=1;
		 #1
		 if(result != 16'hFFFF)
				$display("Failed ASHUI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		 
		 
		 
		//
		// MOV
		//
		op = MOV;
		A=16'hFFeF;
		 B=1;
		 #1
		 if(result != 16'hFFeF)
				$display("Failed MOV A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		//
		// MOVI
		//
		op = MOV;
		A=16'h00eF;
		 B=1;
		 #1
		 if(result != 16'h00eF)
				$display("Failed MOV A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		//
		// XOR
		//
		op = XOR;
		#10
		A = 16'hFFFF;
		B = 16'hFFFF;
		#1
		 if(result != 0)
				$display("Failed XOR A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		#10
		A = 16'h0000;
		B = 16'h0000;
		#1
		 if(result != 0)
				$display("Failed XOR A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		#10
		A = 16'h0000;
		B = 16'hFFFF;
		#1
		 if(result != 16'hFFFF)
				$display("Failed XOR A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		
		#10
		A = 16'hF0F0;
		B = 16'hFFFF;
		#1
		 if(result != 16'h0F0F)
				$display("Failed XOR A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		//
		// XORI
		//
		op = XORI;
		#10
		A = 16'hFFFF;
		B = 16'h00FF;
		#1
		 if(result != 16'hFF00)
				$display("Failed XORI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		#10
		A = 16'h0000;
		B = 16'h0000;
		#1
		 if(result != 0)
				$display("Failed XORI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		#10
		A = 16'h0000;
		B = 16'h00FF;
		#1
		 if(result != 16'h00FF)
				$display("Failed XORI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		
		#10
		A = 16'hFFFF;
		B = 16'h0000;
		#1
		 if(result != 16'hFFFF)
				$display("Failed XORI A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		
		//
		// OR
		//
		op = OR;
		#10
		A = 16'hFFFF;
		B = 16'h00FF;
		#1
		 if(result != 16'hFFFF)
				$display("Failed OR A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		#10
		A = 16'h0000;
		B = 16'h0000;
		#1
		 if(result != 0)
				$display("Failed OR A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		#10
		A = 16'h0000;
		B = 16'hFFFF;
		#1
		 if(result != 16'hFFFF)
				$display("Failed OR A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
		
		//
		// AND
		//
		op = AND;
		#10
		A = 16'hFFFF;
		B = 16'h00FF;
		#1
		 if(result != 16'h00FF)
				$display("Failed AND A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		#10
		A = 16'h0000;
		B = 16'h0000;
		#1
		 if(result != 0)
				$display("Failed AND A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);
				
		#10
		A = 16'hFFFF;
		B = 16'hFFFF;
		#1
		 if(result != 16'hFFFF)
				$display("Failed AND A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);

		//
		// CMP
		//
		op = CMP;
		#10
		A = 16'hFFFF;
		B = 16'h00FF;
		#1
		 if(F[0] != 1)
				$display("Failed CMP A: %b, B: %b, Result: %b, Opcode: %b", A, B, result, op);

		//
		// ADD
		//
		
		#10
		op = ADD;
		A = 2'b10; 
		B = 2'b10;
		#1
		if (result != 4)
			$display("Failed ADD A: %b, B: %b, Result: %b, Opcode: %h", A, B, result, op);
		
		#10
		A = 16'h7fff;
		B = 16'h7fff;
		#1
		if (F[2] != 1)
			$display("Failed ADD A: %b, B: %b, Result: %b, Opcode: %h", A, B, result, op);
					
		#10
		A = 16'h8000;
		B = 16'h8000;
		#1
		if (F[2] != 1)
			$display("Failed ADD A: %b, B: %b, Result: %b, Opcode: %h", A, B, result, op);
			
		//
		// ADDI
		//
		
		#10
		op = ADDI;		
		A = 2'b10;
		B = 2'b10;
		#1
		if (result != 4)
			$display("Failed ADDI A: %b, B: %b, Result: %b, Opcode: %h", A, B, result, op);
			
		#10	
		A = 16'h7fff;
		B = 8'h10;
		#1
		if (F[2] != 1)
			$display("Failed ADDI A: %b, B: %b, Result: %b, Opcode: %h", A, B, result, op);
			

		//
		// ADDCI
		//
		#10
		op = ADDCI;		
		A = 2'b10;
		B = 2'b10;
		Cin = 1'b1;
		#1
		if (result != 5)
			$display("Failed ADDCI A: %b, B: %b, Cin: %b, Result: %b, Opcode: %h", A, B, Cin, result, op);
			
		#10	
		A = 16'h7fff;
		B = 8'h10;
		Cin = 1'b1;
		#1
		if (F[2] != 1)
			$display("Failed ADDCI A: %b, B: %b, Cin: %b, Result: %b, Opcode: %h", A, B, Cin, result, op);
		
		//
		// ADDC
		//
		#10
		op = ADDC;		
		A = 2'b10;
		B = 2'b10;
		Cin = 1'b1;
		#1
		if (result != 5)
			$display("Failed ADDC A: %b, B: %b, Cin: %b, Result: %b, Opcode: %h", A, B, Cin, result, op);
			
		#10	
		A = 16'h7fff;
		B = 8'h10;
		Cin = 1'b1;
		#1
		if (F[2] != 1)
			$display("Failed ADDC A: %b, B: %b, Cin: %b, Result: %b, Opcode: %h", A, B, Cin, result, op);
			
		//
		// ADDU
		//
		#10
		op = ADDU;		
		A = 2'b10;
		B = 2'b10;
		#1
		if (result != 4)
			$display("Failed ADDU A: %b, B: %b, Result: %b, Opcode: %h", A, B, result, op);
			
		#10	
		A = 16'hffff;
		B = 16'hffff;
		#1
		if (F[3] != 1)
			$display("Failed ADDU A: %b, B: %b, Result: %b, Opcode: %h", A, B, result, op);
		
		//
		// SUB
		//
		#10
		op = SUB;
		A = 2'b10; 
		B = 2'b10;
		#1
		if (result != 0)
			$display("Failed SUB A: %b, B: %b, Result: %b, Opcode: %h", A, B, result, op);
		
		#10
		A = 16'h7fff;
		B = 16'hffff;
		#1
		if (F[2] != 1)
			$display("Failed SUB A: %b, B: %b, Result: %b, Opcode: %h", A, B, result, op);
					
		#10
		A = 16'h8000;
		B = 16'h0001;
		#1
		if (F[2] != 1)
			$display("Failed SUB A: %b, B: %b, Result: %b, Opcode: %h", A, B, result, op);
		
		// 
		// SUBI
		//
		
		
		#10
		op = SUBI;
		A = 2'b10; 
		B = 2'b10;
		#1
		if (result != 0)
			$display("Failed SUBI A: %b, B: %b, Result: %b, Opcode: %h", A, B, result, op);
		
		#10
		A = 16'h7fff;
		B = 16'hffff;
		#1
		if (F[2] != 1)
			$display("Failed SUBI A: %b, B: %b, Result: %b, Opcode: %h", A, B, result, op);
					
		#10
		A = 16'h8000;
		B = 16'h0001;
		#1
		if (F[2] != 1)
			$display("Failed SUBI A: %b, B: %b, Result: %b, Opcode: %h", A, B, result, op);
		
		$display("Finished testing!");
				
		 end
		 
endmodule

